//
//  Map.m
//  CarDemo
//
//  Created by huang kun on 8/11/10.
//  Copyright 2010 UESTC. All rights reserved.
//

#import "Map.h"

@interface Map(Private)

- (void) newDirection;
- (BOOL) newPosition:(int)direction;
- (void) push:(int)direction x:(int)x y:(int)y;
- (void) pop;
- (BOOL) empty;
- (void) resetMap;
- (void) resetStack;
- (BOOL) shouldConnected;
@end


@implementation Map

@synthesize isOk;
@synthesize path;


- (id) init {
	if ( (self = [super init]) ){
		inX = 0;
		inY = 6;
		outX = 8;
		outY = 0;
		
		oldX = inX;
		oldY = inY;
		startDirection = RIGHT;
		endDirection = RIGHT;
		currentDirection = startDirection;
		
		if (inX <= outX && inY <= outY)
			firstCheckDirection = UP;
		else if(inX <= outX && inY >= outY)
			firstCheckDirection = RIGHT;
		else if(inX >= outX && inY >= outY)
			firstCheckDirection = DOWN;
		else if(inX >= outX && inY <= outY)
			firstCheckDirection = LEFT;

		
		int i,j;
		for (i= 0; i< roadRow; i++) {
			for(j=0; j< roadColumn; j++){
				BlockShape shape = {kblocked, kblocked, kblocked, kblocked, NO};
				//NSLog(@"%d,%d",i,j);
				array[i][j] = shape;
			}
		}
		
		BlockShape shape2 = {kblocked, kblocked, kblocked, kblocked, YES};
		array[4][3] = shape2;
		
		
		path.top = 0;
	}
	return self;
}

- (BOOL) shouldSet:(int)x y:(int)y {
	if( x >= 0 && y >= 0 && x <= roadWidth-1 && y <= roadHeight-1)
		return !array[x][y].isBlock;
	else 
		return YES;
}

- (BOOL) updateMapArray:(int)x y:(int)y block:(BlockShape)shape {
	if( x >= 0 && y >= 0 && x <= roadWidth-1 && y <= roadHeight-1){
		array[x][y] = shape;
		return YES;
	}
	else 
		return NO;
}

- (BOOL) shouldConnected:(BlockShape)shape{
	switch (endDirection) {
		case UP:
		{
			if (shape.up)return YES;
		}
			break;
		case DOWN:
		{
			if (shape.down)return YES;
		}
			break;
		case LEFT:
		{
			if (shape.left)return YES;
		}
			break;
		case RIGHT:
		{
			if (shape.right)return YES;
		}
			break;
		default:
			break;
	}
	return NO;
}

- (void) push:(int)direction x:(int)x y:(int)y{
	StackNode node = {x, y, direction};
	path.data[path.top] = node;
	path.top++;
	
	int i = path.top - 1;
	switch (path.data[i].direction) {
		case UP:
		{
			printf("push:%d,%d,UP\n",path.data[i].x,path.data[i].y);
		}
			break;
		case DOWN:
		{
			printf("push:%d,%d,DOWN\n",path.data[i].x,path.data[i].y);
		}
			break;
		case LEFT:
		{
			printf("push:%d,%d,LEFT\n",path.data[i].x,path.data[i].y);
		}
			break;
		case RIGHT:
		{
			printf("push:%d,%d,RIGHT\n",path.data[i].x,path.data[i].y);
		}
			break;
		default:
			break;
	}
	
}

- (void) pop {
	if (path.top > 0){
		path.top--;
		switch (path.data[path.top].direction) {
			case UP:
			{
				printf("pop:%d,%d,UP\n",path.data[path.top-1].x,path.data[path.top-1].y);
				array[oldX][oldY].up = ktested;
			}
				break;
			case DOWN:
			{
				printf("pop:%d,%d,DOWN\n",path.data[path.top-1].x,path.data[path.top-1].y);
				array[oldX][oldY].down = ktested;
			}
				break;
			case LEFT:
				{
					printf("pop:%d,%d,LEFT\n",path.data[path.top-1].x,path.data[path.top-1].y);
					array[oldX][oldY].left = ktested;
				}
				break;
			case RIGHT:
				{
					printf("pop:%d,%d,RIGHT\n",path.data[path.top-1].x,path.data[path.top-1].y);
					array[oldX][oldY].right = ktested;
				}
				break;
			default:
				break;
		}
	}	
}

- (BOOL) empty {
	return (path.top == 0);
}

- (void) resetStack {
	path.top = 0;
}

- (BOOL) testMap {
	[self resetStack];
	[self resetMap];
	
	//测试入口
	if ( (startDirection == UP && array[inX][inY].down == kavaliable) )
		array[oldX][oldY].down = kused;
	else if	(startDirection == DOWN && array[inX][inY].up == kavaliable)
		array[oldX][oldY].up = kused;
	else if(startDirection == LEFT && array[inX][inY].right == kavaliable)
		array[oldX][oldY].right = kused;
	else if(startDirection == RIGHT && array[inX][inY].left == kavaliable)
		array[oldX][oldY].left = kused;
	else {
		isOk = NO;
		return isOk;
	}
	currentDirection = firstCheckDirection;
	//[self push:startDirection x:oldX y:oldY];
	

	do {
		//向默认方向探索
		if([self newPosition:currentDirection]){
			//下一步
			
			[self push:currentDirection x:oldX y:oldY];
			
			oldX = newX;
			oldY = newY;
		/*	for (int i= 0; i< path.top; i++) {
				if(path.data[i].direction == UP)printf("上");
				if(path.data[i].direction == DOWN)printf("下");
				if(path.data[i].direction == LEFT)printf("左");
				if(path.data[i].direction == RIGHT)printf("右");
				printf("\n");
			}*/
			currentDirection = firstCheckDirection;
			
			if (newX == outX && newY == outY && [self shouldConnected:array[newX][newY]]){
				isOk = YES;
				[self push:endDirection x:oldX y:oldY];

				return isOk;
			}
		
		}
		else {
			[self newDirection];
		
			//4个方向都不通
		//if (array[oldX][oldY].up != kavaliable && array[oldX][oldY].down != kavaliable
		//		&& array[oldX][oldY].left != kavaliable && array[oldX][oldY].right != kavaliable) {
			if(currentDirection == firstCheckDirection ){
				
					
				[self pop];
		/*	for (int i= 0; i< path.top; i++) {
				if(path.data[i].direction == UP)printf("上");
				if(path.data[i].direction == DOWN)printf("下");
				if(path.data[i].direction == LEFT)printf("左");
				if(path.data[i].direction == RIGHT)printf("右");
				printf("\n");
			}*/
				if( ![self empty] ){
					oldX = path.data[path.top].x;
					oldY = path.data[path.top].y;
					currentDirection = path.data[path.top].direction;
					printf("after pop:%d,%d,%d\n",oldX,oldY,currentDirection);


					switch (currentDirection) {
						case UP:
						{
					//		NSLog(@"UP");
							array[oldX][oldY].up = ktested;
						}
							break;
						case DOWN:
						{
					//		NSLog(@"DOWN");
							array[oldX][oldY].down = ktested;
						}
							break;
						case LEFT:
						{
					//		NSLog(@"LEFT");
							array[oldX][oldY].left = ktested;
						}
							break;
						case RIGHT:
						{
						//	NSLog(@"RIGHT");
							array[oldX][oldY].right = ktested;
						}
							break;
						default:
							break;
					}
				}
			}
		}
		
	}while( ! ([self empty] && array[oldX][oldY].up != kavaliable && array[oldX][oldY].down != kavaliable
			   && array[oldX][oldY].left != kavaliable && array[oldX][oldY].right != kavaliable));
	isOk = NO;
	
	return NO;
	/*
	
		if (newX > roadRow-1 || newX < 0 || newY > roadColumn-1 || newY < 0) {
			if (newX == outX && newY == outY) {
				isOk = YES;
				break;
			}
			isOut = NO;
			isOk = NO;
			break;
			else {
				isOut = YES;
			}
		}
		else if ([self shouldConnected:array[newX][newY]]){
		}
		
		
		[self newDirection];
		oldX = newX;
		oldY = newY;
	} while (isOut);
	
	*/
}

- (void) resetMap {
	//测试后还原地图
	for (int i= 0; i< roadRow; i++) {
		for(int j=0; j< roadColumn; j++){
			if(array[i][j].up > 1)array[i][j].up = 1;
			if(array[i][j].down > 1)array[i][j].down = 1;
			if(array[i][j].left > 1)array[i][j].left = 1;
			if(array[i][j].right > 1)array[i][j].right = 1;
		}
	}
	oldX = inX;
	oldY = inY;
	newX = oldX;
	newY = oldY;
	
	/*
	for(int i=0;i<path.top;i++){
		switch (path.data[i].direction) {
			case UP:
			{
				printf("%d,%d,UP\n",path.data[i].x,path.data[i].y);
			}
				break;
			case DOWN:
			{
				printf("%d,%d,DOWN\n",path.data[i].x,path.data[i].y);
			}
				break;
			case LEFT:
			{
				printf("%d,%d,LEFT\n",path.data[i].x,path.data[i].y);
			}
				break;
			case RIGHT:
			{
				printf("%d,%d,RIGHT\n",path.data[i].x,path.data[i].y);
			}
				break;
			default:
				break;
		}
	}
	*/
}

- (void) newDirection {
	//顺时针
	if (currentDirection == LEFT){
		currentDirection = UP;
		NSLog(@"LEFT->UP");
	}
	else if(currentDirection == UP){
		currentDirection = RIGHT;
		NSLog(@"UP->RIGHT");
	}
	else if(currentDirection == RIGHT){
		currentDirection = DOWN;
		NSLog(@"RIGHT->DOWN");
	}
	else if(currentDirection == DOWN){
		currentDirection = LEFT;
		NSLog(@"DOWN->LEFT");
	}
}

- (BOOL) newPosition:(int)direction {
	switch (direction) {
		case UP:
		{
			if( array[oldX][oldY].up != kavaliable)
				return NO;
			
			newY = oldY+1;
			newX = oldX;
			
			if (newY > roadHeight-1){
				//越界
				newY = oldY;
				array[oldX][oldY].up = ktested;
				return NO;
			}
			else if(array[newX][newY].down > kavaliable){
				//不行
				array[oldX][oldY].up = ktested;
				array[newX][newY].down = ktested;
				newY = oldY;
				return NO;
			}
			else if(array[newX][newY].down == kblocked){
				array[oldX][oldY].up = ktested;
				newY = oldY;
				return NO;
			}
			
			array[oldX][oldY].up = kused;
			array[newX][newY].down = kused;
			
		}
			break;
		case DOWN:
		{
			if( array[oldX][oldY].down != kavaliable)
				return NO;
			
			newY = oldY-1;
			newX = oldX;
			if (newY < 0){
				//越界
				newY = oldY;
				array[oldX][oldY].down = ktested;
				return NO;
			}
			else if(array[newX][newY].up > kavaliable){
				//不行
				array[oldX][oldY].down = ktested;
				array[newX][newY].up = ktested;
				newY = oldY;
				return NO;
			}
			else if(array[newX][newY].up == kblocked){
				array[oldX][oldY].down = ktested;
				newY = oldY;
				return NO;
			}
			
			array[oldX][oldY].down = kused;
			array[newX][newY].up = kused;
		
		}
			break;
		case LEFT:
		{
			if( array[oldX][oldY].left != kavaliable)
				return NO;
			
			newY = oldY;
			newX = oldX-1;
			if (newX < 0){
				//越界
				newX = oldX;
				array[oldX][oldY].left = ktested;
				return NO;
			}
			else if(array[newX][newY].right > kavaliable){
				//不行
				array[oldX][oldY].left = ktested;
				array[newX][newY].right = ktested;
				newX = oldX;
				return NO;
			}
			else if(array[newX][newY].right == kblocked){
				array[oldX][oldY].left = ktested;
				newX = oldX;
				return NO;
			}
			
			array[oldX][oldY].left = kused;
			array[newX][newY].right = kused;
			
		}
			break;
		case RIGHT:
		{
			if( array[oldX][oldY].right != kavaliable)
				return NO;
			
			newY = oldY;
			newX = oldX+1;
			if (newX > roadWidth -1){
				//越界
				newX = oldX;
				array[oldX][oldY].right = ktested;
				return NO;
			}
			else if(array[newX][newY].left > kavaliable){
				//不行
				array[oldX][oldY].right = ktested;
				array[newX][newY].left = ktested;
				newX = oldX;
				return NO;
			}
			else if(array[newX][newY].left == kblocked){
				array[oldX][oldY].right = ktested;
				newX = oldX;
				return NO;
			}
			
			array[oldX][oldY].right = kused;
			array[newX][newY].left = kused;
		
		}
			break;
		default:
			break;
	}
	return YES;
}



@end
